/*
 * @description:
 * @author: <a href="mailto:joshualwork@163.com">joshua_liu</a>
 * @Date: 2024-02-09 12:06:23
 * @FilePath: \dynamic-conf\main.go
 * @LastEditTime: 2024-03-26 23:22:41
 * @LastEditors: <a href="mailto:joshualwork@163.com">joshua_liu</a>
 */
package main

import (
	"fmt"
	"net/http"
	"strings"

	"dynamic-conf/middleware"
	"dynamic-conf/utils"

	"dynamic-conf/fo"
	custHttp "dynamic-conf/http"

	"github.com/joshua-liu-github/dynamic-conf/loader"

	log "github.com/joshua-liu-github/dynamic-conf/logger"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)

// 自定义端口
var (
	globalConfig = loader.GlobalConfig
	addr         = fmt.Sprintf(":%d", globalConfig.GetInt("p"))
	propsArr     = loader.GetExtraPropsFromLoader()
)

func main() {
	log.Info("Starting dynamic configuration application...")
	realCli, err := middleware.New()
	if err == nil {
		for _, key := range propsArr {
			content, err := realCli.GetContent(key.DataId, key.Group)
			log.Info(fmt.Sprintf("Nacos group : '%s', data-id : '%s', content: '%s", key.Group, key.DataId, content))
			if err == nil {
				fo.Writefile2Path(key.ToPath, content)
			}
			realCli.WatchContent(key.DataId, key.Group, WatchCallback)

		}
		http.Handle("/metrics", authMiddleware(promhttp.Handler()))
		log.Info("Ready to listen http metrics port %s", addr)
		log.Fatal(fmt.Sprintf("%s", http.ListenAndServe(addr, nil)))
	}
}

func WatchCallback(dataId string, group string, content string) {
	log.Info("Receive watch callback info")
	headersMap := make(map[string]string)
	for _, key := range propsArr {
		if strings.EqualFold(key.DataId, dataId) && strings.EqualFold(key.Group, group) {
			fo.Writefile2Path(key.ToPath, content)
		}
		headersMap["Content-Type"] = "application/x-www-form-urlencoded"
		if len(key.Callback) > 0 {
			if len(key.Authorization) > 0 {
				headersMap["Authorization"] = key.Authorization
			}
			custHttp.EasyHttpRequest("POST", key.Callback, headersMap, nil)
		}
	}
}

func authMiddleware(h http.Handler) http.Handler {
	if globalConfig.IsSet("application.basic-auth-users") {
		return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
			log.Debug("Check auth info")
			u, p, ok := r.BasicAuth()
			userMap := globalConfig.GetStringMap("application.basic-auth-users")
			encodeUserInfo, ok1 := userMap[u].(string)
			if !ok1 {
				w.Header().Set("WWW-Authenticate", `Basic realm="metrics"`)
				http.Error(w, "Unauthorized.", http.StatusUnauthorized)
				return
			}
			validateResult := utils.ComparePasswords(encodeUserInfo, p)
			if !ok || !validateResult {
				w.Header().Set("WWW-Authenticate", `Basic realm="metrics"`)
				http.Error(w, "Unauthorized.", http.StatusUnauthorized)
				return
			}
			h.ServeHTTP(w, r)
		})
	}
	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		h.ServeHTTP(w, r)
	})
}
